package com.robot.admin.controller;

import com.robot.admin.pojo.Admin;
import com.robot.admin.service.AdminService;
import entity.PageResult;
import entity.Result;
import entity.StatusCode;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import util.CheckUtil;
import util.JwtUtil;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * admin控制器层
 *
 * @author wuyunbin
 */
@RestController
@CrossOrigin
@RequestMapping("/admin")
public class AdminController {

    @Autowired
    private AdminService adminService;

    @Autowired
    private CheckUtil checkUtil;

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private BCryptPasswordEncoder encoder;

    @Autowired
    private HttpServletRequest request;


    /**
     * 查询全部数据
     *
     * @return
     */
    @RequestMapping(method = RequestMethod.GET)
    public Result findAll() {
        return new Result(StatusCode.SUCCESS_QUERY, adminService.findAll());
    }

    /**
     * 根据ID查询
     *
     * @param id ID
     * @return
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public Result findById(@PathVariable String id) {
        return new Result(StatusCode.SUCCESS_QUERY, adminService.findById(id));
    }

    /**
     * 分页+多条件查询
     *
     * @param searchMap 查询条件封装
     * @param page      页码
     * @param size      页大小
     * @return 分页结果
     */
    @RequestMapping(value = "/search/{page}/{size}", method = RequestMethod.POST)
    public Result findSearch(@RequestBody Map searchMap, @PathVariable int page, @PathVariable int size) {
        Page<Admin> pageList = adminService.findSearch(searchMap, page, size);
        return new Result(StatusCode.SUCCESS_QUERY, new PageResult<Admin>(pageList.getTotalElements(), pageList.getContent()));
    }

    /**
     * 根据条件查询
     *
     * @param searchMap
     * @return
     */
    @RequestMapping(value = "/search", method = RequestMethod.POST)
    public Result findSearch(@RequestBody Map searchMap) {
        return new Result(StatusCode.SUCCESS_QUERY, adminService.findSearch(searchMap));
    }

    /**
     * 增加
     *
     * @param admin
     */
    @RequestMapping(method = RequestMethod.POST)
    public Result add(@RequestBody Admin admin) {
        adminService.add(admin);
        return new Result(StatusCode.SUCCESS_DELETED);
    }

    /**
     * 修改
     *
     * @param admin
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    public Result update(@RequestBody Admin admin, @PathVariable String id) {
        admin.setId(id);
        Claims claims = (Claims) request.getAttribute("robot_admin");
        if (claims == null) {
            return new Result(StatusCode.ERROR_TOKEN_EXPIRED);
        }
        admin.setPassword(encoder.encode(admin.getPassword()));
        adminService.update(admin);
        return new Result(StatusCode.SUCCESS_UPDATED);
    }

    /**
     * 删除
     *
     * @param id
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public Result delete(@PathVariable String id) {
        adminService.deleteById(id);
        return new Result(StatusCode.SUCCESS_DELETED);
    }

    /**
     * 发送短信验证码
     *
     * @param phone
     * @param map
     * @return
     */
    @PostMapping("/sendSms/{phone}")
    public Result sendSms(@PathVariable String phone, @RequestBody Map map) {
        //检查手机号
        if (!checkUtil.checkPhone(phone)) {
            return new Result(StatusCode.ERROR_INVALID_PHONE);
        }
        //检查场景值
        String mapKey = "flag";
        if (map.get(mapKey) == null) {
            return new Result(StatusCode.ERROR_FLAG_MISSING);
        }
        String flag = map.get(mapKey).toString();
        //非空验证
        if (flag == null || "".equals(flag.trim())) {
            return new Result(StatusCode.ERROR_FLAG_MISSING);
        }

        if (!adminService.isCorrectScene(flag)) {
            return new Result(StatusCode.ERROR_FLAG_INVALID);
        }

        if (!adminService.sendSms(phone, flag)) {
            return new Result(StatusCode.ERROR_SEND_TOO_MANY_SMS);
        }

        return new Result(StatusCode.SUCCESS_SEND);
    }


    /**
     * 通过手机和验证码登录管理员账号
     *
     * @param admin     admin
     * @param checkCode 验证码
     * @return Result
     */
    @RequestMapping(value = "/login/phone/{checkCode}", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public Result loginByPhoneSms(@RequestBody Admin admin, @PathVariable String checkCode) {
        String phone = admin.getPhone();
        if (!checkUtil.checkPhone(phone)) {
            return new Result(StatusCode.ERROR_INVALID_PHONE);
        }

        checkCode = checkCode.trim();
        if ("".equals(checkCode)) {
            return new Result(StatusCode.ERROR_VERIFICATION_CODE);
        }
        //验证码是不是过期
        String scene = "login";
        if (!adminService.isCheckCodeExpire(scene, phone)) {
            return new Result(StatusCode.ERROR_VERIFICATION_CODE_EXPIRED);
        }
        //验证码是否正确
        if (!adminService.isCorrectCheckCode(scene, phone, checkCode)) {
            return new Result(StatusCode.ERROR_VERIFICATION_CODE);
        }

        //根据手机号取出数据库中的数据
        Admin adminInDb = adminService.findAdminByPhone(phone);
        if (adminInDb == null) {
            return new Result(StatusCode.ERROR_ADMIN_DOES_NOTE_EXIST);
        }
        HashMap<String, String> map = new HashMap<>(2);
        map.put("token", jwtUtil.createJwt(adminInDb.getId(), admin.getPhone(), "admin"));
        map.put("role", "admin");
        //删除redis里面的验证码
        adminService.deleteCheckCode(scene, phone);
        return new Result(StatusCode.SUCCESS_LOGIN, map);
    }

    /**
     * 通过手机和密码登录管理员账号
     *
     * @param admin admin
     * @return Result
     */
    @RequestMapping(value = "/login", method = {RequestMethod.POST})
    @Transactional(rollbackFor = Exception.class)
    public Result loginByPassword(@RequestBody Admin admin) {
        String phone = admin.getPhone();
        if (!checkUtil.checkPhone(phone)) {
            return new Result(StatusCode.ERROR_INVALID_PHONE);
        }
        Admin adminInDb = adminService.findAdminByPhone(phone);
        //判断admin是否存在
        if (adminInDb == null) {
            return new Result(StatusCode.ERROR_ADMIN_DOES_NOTE_EXIST);
        }
        //判断密码
        if (!encoder.matches(admin.getPassword(), adminInDb.getPassword())) {
            return new Result(StatusCode.ERROR_PASSWORD_WRONG);
        }

        HashMap<String, String> map = new HashMap<>(2);
        map.put("token", jwtUtil.createJwt(adminInDb.getId(), admin.getPhone(), "admin"));
        map.put("role", "admin");
        
        return new Result(StatusCode.SUCCESS_LOGIN, map);
    }

    /**
     * 管理员更换密码
     *
     * @param checkCode 短信验证码
     * @param admin
     * @return Result
     */
    @RequestMapping(value = "/updatePassword/{checkCode}", method = RequestMethod.PUT)
    @Transactional(rollbackFor = Exception.class)
    public Result updatePassword(@PathVariable String checkCode, @RequestBody Admin admin) {
        Claims claims = (Claims) request.getAttribute("robot_admin");
        //判断是否登录
        if (claims == null) {
            return new Result(StatusCode.ERROR_TOKEN_EXPIRED);
        }
        Admin adminInDb = adminService.findById(claims.getId());
        if (adminInDb == null) {
            return new Result(StatusCode.ERROR_ADMIN_DOES_NOTE_EXIST);
        }

        String phone = admin.getPhone();
        if (phone.isEmpty()) {
            return new Result(StatusCode.ERROR_PHONE_REQUIRED);
        }
        if (!checkUtil.checkPhone(phone)) {
            return new Result(StatusCode.ERROR_INVALID_PHONE);
        }
        if (!adminInDb.getPhone().equals(phone)) {
            return new Result(StatusCode.ERROR, "手机号和登录的管理员手机号不一致");
        }

        String scene = "updatePassword";
        //验证码是不是过期
        if (!adminService.isCheckCodeExpire(scene, phone)) {
            return new Result(StatusCode.ERROR_VERIFICATION_CODE_EXPIRED);
        }
        //验证码是否正确
        if (!adminService.isCorrectCheckCode(scene, phone, checkCode)) {
            return new Result(StatusCode.ERROR_VERIFICATION_CODE);
        }

        //更新密码
        adminInDb.setPassword(encoder.encode(admin.getPassword()));
        adminInDb.setUpdatedAt(LocalDateTime.now());
        adminService.update(adminInDb);
        adminService.deleteCheckCode(scene, phone);
        return new Result(StatusCode.SUCCESS_UPDATED);
    }

    /**
     * 管理员找回密码
     *
     * @param checkCode 短信验证码
     * @param admin
     * @return Result
     */
    @RequestMapping(value = "/findPassword/{checkCode}", method = RequestMethod.PUT)
    @Transactional(rollbackFor = Exception.class)
    public Result findPassword(@PathVariable String checkCode, @RequestBody Admin admin) {
        String phone = admin.getPhone();
        if (phone.isEmpty()) {
            return new Result(StatusCode.ERROR_PHONE_REQUIRED);
        }

        String scene = "findPassword";
        //验证码是不是过期
        if (!adminService.isCheckCodeExpire(scene, phone)) {
            return new Result(StatusCode.ERROR_VERIFICATION_CODE_EXPIRED);
        }
        //验证码是否正确
        if (!adminService.isCorrectCheckCode(scene, phone, checkCode)) {
            return new Result(StatusCode.ERROR_VERIFICATION_CODE);
        }

        //更新密码
        Admin adminInDb = adminService.findAdminByPhone(phone);
        if (adminInDb == null) {
            return new Result(StatusCode.ERROR_ADMIN_DOES_NOTE_EXIST);
        }
        adminInDb.setPassword(encoder.encode(admin.getPassword()));
        adminInDb.setUpdatedAt(LocalDateTime.now());
        adminService.update(adminInDb);
        adminService.deleteCheckCode(scene, phone);
        return new Result(StatusCode.SUCCESS_UPDATED);
    }

}